/*
 * LinuxX11OS.cpp
 *
 *  Created on: 17.02.2011
 *      Author: dis
 */

#include <iostream>
#include <errno.h>

#include <time.h>
#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

#include "LinuxX11OS.h"

using namespace std;

unsigned long Sys_Milliseconds(void) {
	struct timeval tp;
	gettimeofday(&tp, NULL/*&tzp*/);
	return tp.tv_sec * 1000 + tp.tv_usec / 1000;
}

bool LinuxX11OS::propertyText(Window window, Atom prop, char* buffer, int size) {
	XTextProperty tp;
	*buffer = 0;
	if (!XGetTextProperty(display, window, &tp, prop)) {
		return false;
	}
	if (tp.nitems > 0) {
		int count = 0, i, ret;
		char **list = NULL;
		ret = XmbTextPropertyToTextList(display, &tp, &list, &count);
		if ((ret == Success || ret > 0) && list != NULL) {
			/*for (i = 0; i < count; i++)*/
			snprintf(buffer, size, "%s", list[0]);
			/*printf("%s,%i", list[i], i);*/
			XFreeStringList(list);
		} else {
			snprintf(buffer, size, "%s", tp.value);
		}
		return true;
	}
	return false;

}

void* LinuxX11OS::property(Window win, Atom prop, Atom type, int *nitems) {
	Atom type_ret;
	int format_ret;
	unsigned long items_ret;
	unsigned long after_ret;
	unsigned char *prop_data = 0;

	// на основании атома и его типа берём значение свойства
	if (XGetWindowProperty(display, win, prop, 0, 0x7fffffff, False, type,
			&type_ret, &format_ret, &items_ret, &after_ret, &prop_data)
			!= Success)
		return 0;

	// количество полученных элементов
	if (nitems)
		*nitems = items_ret;

	return prop_data;
}

Activity* LinuxX11OS::getActivity() {
	int num = 0;
	ulong time = Sys_Milliseconds();
	Window* win = reinterpret_cast<ulong *> (property(
			DefaultRootWindow(display), NET_ACTIVE_WINDOW, XA_WINDOW, &num));

	static char buffer[8 * 1024];
	propertyText(*win, WM_ICON_NAME, buffer, 8 * 1024);

	//char* winName = reinterpret_cast<char *> (property(*win, WM_ICON_NAME,AnyPropertyType, &num));
	Activity* aWin = new Activity(*win,buffer , time, 1);

	ulong* pid = reinterpret_cast<ulong *> (property(*win, NET_WM_PID,
			AnyPropertyType, &num));
	char* appName = reinterpret_cast<char *> (property(*win, WM_CLASS,
			AnyPropertyType, &num));

	setCurrent(new Activity(*pid, appName, time, 0, aWin));

	XFree(win);
	XFree(pid);
	XFree(appName);
	//XFree(winName);
	return current;
}

void LinuxX11OS::setCurrent(Activity* newCurrent) {
	if (current != 0) {
		delete current;
	}
	current = newCurrent;
}

LinuxX11OS::LinuxX11OS() {
	current = 0;
	display = NULL;
	NET_ACTIVE_WINDOW = 0;
	NET_WM_PID = 0;
	WM_ICON_NAME = 0;
	WM_CLASS = 0;
}

LinuxX11OS::~LinuxX11OS() {
	/* Закрыть соединение с X сервером */
	if (display != NULL) {
		XCloseDisplay(display);
	}
	setCurrent(0);
}

bool LinuxX11OS::init() {
#ifndef NO_I18N
	{
		char *lc;
		lc = setlocale(LC_ALL, "");
		if (!lc)
			fprintf(stderr, "can not set locale properly\n");
	}
#endif

	/* Соединиться с X сервером, если X сервер на удаленной машине
	 * следует разрешить на машине, где запущен X Server
	 * удаленные соединения командой xhost+ (см. man xhost)
	 */

	if ((display = XOpenDisplay(getenv("DISPLAY"))) == NULL) {
		cerr << "Can't connect X server: " << strerror(errno) << endl;
		return false;
	}

	NET_ACTIVE_WINDOW = XInternAtom(display, "_NET_ACTIVE_WINDOW", False);
	NET_WM_PID = XInternAtom(display, "_NET_WM_PID", True);
	WM_ICON_NAME = XInternAtom(display, "WM_ICON_NAME", True);
	WM_CLASS = XInternAtom(display, "WM_CLASS", True);

	return true;
}

void LinuxX11OS::clean() {
}
